//
//  PlayLayer.cpp
//  test
//
//  Created by x86mac on 15-8-12.
//
//

#include "PlayLayer.h"

PlayLayer::PlayLayer()
:mMatrixLeftBottomX(0)
,mMatrixLeftBottomY(0)
,selAnimalIndex(Index(-1,-1))
,swapAnimalIndex(Index(-1,-1)) 
,isTouchMoved(true)
{
    for (int r = 0; r < GameData::HEIGHT_NUM; ++r) 
    {
        for (int c = 0; c < GameData::WIDTH_NUM; ++c)
        {
            animalMatrix[r][c] = nullptr;
        }
    }
}


Scene* PlayLayer::createScene()
{
    auto scene = Scene::create();
    auto layer = PlayLayer::create();
    scene->addChild(layer);
    return scene;
}

bool PlayLayer::init()
{
    if (!Layer::init()) 
    {
        return false;
    }
    auto size = Director::getInstance()->getWinSize();
    
    mMatrixLeftBottomX = (size.width - Animal::getContentWidth()*GameData::WIDTH_NUM - (GameData::WIDTH_NUM-1)*GameData::SPACE)/2;
    mMatrixLeftBottomY = (size.height - Animal::getContentWidth()*GameData::HEIGHT_NUM - (GameData::HEIGHT_NUM-1)*GameData::SPACE)/2;
    
    
    
    initMatrix();
    removeAnimal();
    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->onTouchBegan = CC_CALLBACK_2(PlayLayer::onTouchBegan, this);
    touchListener->onTouchEnded = CC_CALLBACK_2(PlayLayer::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
    
    
    
    
    return true;
}
bool PlayLayer::onTouchBegan(Touch *touch, Event *unused_event)
{
    selAnimalIndex.first = 0;
    selAnimalIndex.second = 0;
    swapAnimalIndex.first = 0;
    swapAnimalIndex.second = 0;
    bool canTouch = false;
    auto location = touch->getLocation();
    Rect  rectCanTouch = Rect(0,0,0,0);
    rectCanTouch.origin = (Point(mMatrixLeftBottomX,mMatrixLeftBottomY));
    rectCanTouch.size = Size(Animal::getContentWidth() * GameData::WIDTH_NUM + (GameData::WIDTH_NUM - 1) * GameData::SPACE,
        Animal::getContentWidth() * GameData::HEIGHT_NUM + (GameData::HEIGHT_NUM - 1) *GameData::SPACE);
    if (rectCanTouch.containsPoint(location)) 
    {
        selAnimalIndex = getAnimalIndexForTouched(&location);
        canTouch = true;
    }
    return canTouch;
}
void PlayLayer::onTouchEnded(Touch *touch, Event *unused_event)
{   
    do
    {
        int row = selAnimalIndex.first;
        int col = selAnimalIndex.second; 
        auto location = touch->getLocation();
        Point startPoint = getPositionOfAnimal(row, col);
        int width = abs(location.x - startPoint.x);
        int height = abs(location.y - startPoint.y);
        if (width < 10 || height < 10 ||!isTouchMoved) 
        {
            break;
        }
        
        if (height > width) 
        {
            if (location.y > startPoint.y) 
            {
                //上滑
                CC_BREAK_IF(row >= GameData::HEIGHT_NUM-1);
                row++;
                swapAnimalIndex = Index(row, col);
            }
            else
            {
                //下滑
                CC_BREAK_IF(row < 1);
                row--;
                swapAnimalIndex = Index(row, col);
            }
        }
        else
        {
            if (location.x > startPoint.x) 
            {
                //右滑
                CC_BREAK_IF(col >= GameData::WIDTH_NUM-1);
                col++;
                swapAnimalIndex = Index(row, col);
            }
            else
            {
                //左滑 
                CC_BREAK_IF(col < 1);
                col--;
                swapAnimalIndex = Index(row, col);
            }
        }
        isTouchMoved = false;
        swapTwoAnimal();
        runAction(Sequence::create(DelayTime::create(0.5f),
                                   CallFunc::create(CC_CALLBACK_0(PlayLayer::removeAnimal, this)),
                                   DelayTime::create(0.5f),
                                   CallFunc::create(CC_CALLBACK_0(PlayLayer::setIsTouchMoved, this)),
                                   NULL));
        
    }while(0);
}

void PlayLayer::setIsTouchMoved()
{
    isTouchMoved = true;
}

void PlayLayer::swapTwoAnimal()
{
    float dur = 0.3f;
    int r1 = selAnimalIndex.first;
    int c1 = selAnimalIndex.second;
    int r2 = swapAnimalIndex.first;
    int c2 = swapAnimalIndex.second;
    animalMatrix[r1][c1]->runAction(MoveTo::create(dur,getPositionOfAnimal(r2, c2)));
    animalMatrix[r2][c2]->runAction(MoveTo::create(dur,getPositionOfAnimal(r1, c1)));
    Animal* temp = animalMatrix[r1][c1];
    animalMatrix[r1][c1] = animalMatrix[r2][c2];
    animalMatrix[r2][c2] = temp;
}

void PlayLayer::removeAndCreate()
{
}

void PlayLayer::initMatrix()
{
    for (int r = 0; r < GameData::HEIGHT_NUM; ++r) 
    {
        for (int c = 0; c < GameData::WIDTH_NUM; ++c)
        {
            Animal* animal = Animal::createAnimal();
            animal->setAnchorPoint(Point::ZERO);
            animal->setPosition(getPositionOfAnimal(r, c));
            animalMatrix[r][c] = animal;
            addChild(animal);
        }
    }
    
}

//消除三连
void PlayLayer::removeAnimal()
{
    bool removed = false;
    for (int r = 0; r < GameData::HEIGHT_NUM; ++r) 
    {
        int sameNum = 0;
        for (int c = 0 ; c < GameData::WIDTH_NUM - 1; ++c)
        {
            if (animalMatrix[r][c] == nullptr)
            {
                removed = true;
            }
            CC_BREAK_IF(animalMatrix[r][c] == nullptr);
            CC_BREAK_IF(animalMatrix[r][c + 1] == nullptr);
            int num = animalMatrix[r][c]->getImageNumber();
            if (animalMatrix[r][c + 1]->getImageNumber() == num) 
            {
                sameNum++;
            }else
            {
                sameNum = 0; 
            }
            if (sameNum >= 2) 
            {
                animalMatrix[r][c - 1]->setCanRemove(true);
                animalMatrix[r][c]->setCanRemove(true);
                animalMatrix[r][c + 1]->setCanRemove(true);
            }
        }
    }
    
    for (int c = 0; c < GameData::WIDTH_NUM; ++c) 
    {
        int sameNum = 0;
        for (int r = 0 ; r < GameData::HEIGHT_NUM - 1; ++r)
        {
            CC_BREAK_IF(animalMatrix[r][c] == nullptr);
            CC_BREAK_IF(animalMatrix[r + 1][c] == nullptr);
            int num = animalMatrix[r][c]->getImageNumber();
            if (animalMatrix[r + 1][c]->getImageNumber() == num) 
            {
                sameNum++;
            }else
            {
                sameNum = 0; 
            }
            if (sameNum >= 2) 
            {
                animalMatrix[r - 1][c]->setCanRemove(true);
                animalMatrix[r][c]->setCanRemove(true);
                animalMatrix[r + 1][c]->setCanRemove(true);
            }
        }
    }
    for (int r = 0; r < GameData::HEIGHT_NUM; ++r)
    {
        for (int c = 0; c < GameData::WIDTH_NUM; ++c)
        {
            CC_BREAK_IF(animalMatrix[r][c] == nullptr);
            if (animalMatrix[r][c]->getCanRemove())
            {
                animalMatrix[r][c]->runAction(RemoveSelf::create());
                animalMatrix[r][c] = nullptr;
                removed = true;
            }
        }
    }

    if (removed)
    {
        runAction(Sequence::create(DelayTime::create(0.3f),
                                   CallFunc::create(CC_CALLBACK_0(PlayLayer::down, this)),
                                   DelayTime::create(0.3f),
                                   CallFunc::create(CC_CALLBACK_0(PlayLayer::createAndDropAnimal, this)),
                                   nullptr));
    }
}

void PlayLayer::down()
{
    for (int r = 0; r < GameData::HEIGHT_NUM - 1; ++r) 
    {
        for (int c = 0; c < GameData::WIDTH_NUM; ++c)
        {
            if (animalMatrix[r][c] == nullptr) 
            {
                for (int i = r + 1; i < GameData::HEIGHT_NUM; ++i) 
                {
                    if (animalMatrix[i][c] != nullptr) 
                    {
                        animalMatrix[i][c]->runAction(MoveTo::create(0.3f,
                                                                     getPositionOfAnimal(r, c)));
                        animalMatrix[r][c] = animalMatrix[i][c];
                        animalMatrix[i][c] = nullptr;
                        break;
                    }
                }
            }
        }
    }
}

void PlayLayer::createAndDropAnimal()
{
    bool changed = false;
    for (int r = 0; r < GameData::HEIGHT_NUM; ++r) 
    {
        for (int c = 0; c < GameData::WIDTH_NUM; ++c)
        {
            if (animalMatrix[r][c] == nullptr) 
            {
                for (int i = r; i < GameData::HEIGHT_NUM; i++) 
                {
                    if (animalMatrix[i][c] == nullptr) 
                    {
                        Animal* animal = Animal::createAnimal();
                        animal->setAnchorPoint(Point::ZERO);
                        animal->setPosition(getPositionOfAnimal(i, c).x,GameData::HEIGHT_NUM* 70 + 100);
                        animalMatrix[i][c] = animal;
                        addChild(animal);
                        animalMatrix[i][c]->runAction(MoveTo::create(0.5f, getPositionOfAnimal(i, c)));
                        changed = true;
                    }
                }
            }
        }
    }
    if (changed)
    {
        runAction(Sequence::create(DelayTime::create(0.5f),
                                   CallFunc::create(CC_CALLBACK_0(PlayLayer::removeAnimal, this)),
                                   nullptr));
    }
}

Point PlayLayer::getPositionOfAnimal(int row, int col)
{
    Point point;
    point.x = mMatrixLeftBottomX + col*(Animal::getContentWidth() + GameData::SPACE);//+ Animal::getContentWidth()/2;
    point.y = mMatrixLeftBottomY + row*(Animal::getContentWidth() + GameData::SPACE);//+ Animal::getContentWidth()/2;
    return point;
}

Index PlayLayer::getAnimalIndexForTouched(Point *point)
{
    Index index = Index(-1,-1);
    Animal* animal = nullptr;
    Rect rect = Rect(0, 0, 0, 0);
    for (int r = 0; r < GameData::HEIGHT_NUM; r++)
    {
        for (int c = 0; c < GameData::WIDTH_NUM; c++)
        {
            animal = animalMatrix[r][c];
            if (animal != nullptr) 
            {
                rect.origin = getPositionOfAnimal(r, c);
                rect.size = Size(animal->getContentWidth()+GameData::SPACE,animal->getContentWidth()+GameData::SPACE);
                if (rect.containsPoint(*point))
                {
                    index.first = r;
                    index.second = c;
                    return index;
                }
            }
        }
    }
    return index;
}